package com.um.jdy.common.push.service.impl;

import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.um.jdy.common.base.enums.YesOrNo;
import com.um.jdy.common.charge.entity.po.DataLog;
import com.um.jdy.common.charge.entity.po.EvOrder;
import com.um.jdy.common.charge.entity.po.Order;
import com.um.jdy.common.charge.enums.OrderAction;
import com.um.jdy.common.charge.enums.OrderEnum;
import com.um.jdy.common.charge.enums.OrderStopReason;
import com.um.jdy.common.charge.service.DataLogService;
import com.um.jdy.common.charge.service.EbOrderService;
import com.um.jdy.common.charge.service.EvOrderService;
import com.um.jdy.common.commons.manager.WxManager;
import com.um.jdy.common.device.entity.po.Pile;
import com.um.jdy.common.device.entity.po.Station;
import com.um.jdy.common.device.enums.DeviceEnum;
import com.um.jdy.common.device.service.PileService;
import com.um.jdy.common.device.service.StationService;
import com.um.jdy.common.member.entity.po.MemberUser;
import com.um.jdy.common.member.service.MemberUserService;
import com.um.jdy.common.platform.entity.po.Merchant;
import com.um.jdy.common.platform.entity.po.Notification;
import com.um.jdy.common.platform.service.MerchantService;
import com.um.jdy.common.platform.service.NotificationService;
import com.um.jdy.common.push.service.PushService;
import com.um.jdy.rpc.ev.enums.StopType;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author 邓南辉
 * 日期 2024/1/23
 * 版权所有 广州优匠科技有限公司
 */

@Component
@Slf4j
public class PushServiceImpl implements PushService {

    @Autowired
    NotificationService notificationService;

    @Autowired
    MemberUserService memberUserService;

    @Autowired
    StationService stationService;

    @Autowired
    MerchantService merchantService;

    @Autowired
    PileService pileService;

    @Autowired
    EvOrderService evOrderService;

    @Autowired
    EbOrderService ebOrderService;

    @Autowired
    TaskScheduler taskScheduler;

    @Autowired
    WxManager wxManager;

    @Autowired
    DataLogService dataLogService;

    private void pushMiniTemplateMsg(Order order,WxMaSubscribeMessage subscribeMessage){
        try {
            wxManager.getMiniService(order.getComId()).getMsgService().sendSubscribeMsg(subscribeMessage);
            saveChargeData(order.getComId(),order.getChargeOrderId(),subscribeMessage,"推送消息成功！");
            log.info("推送微信小程序订阅消息：{}", JSONUtil.toJsonStr(subscribeMessage));
        } catch (Exception e){
            saveChargeData(order.getComId(),order.getChargeOrderId(),subscribeMessage,"推送消息失败："+e.getMessage());
            log.error("推送微信小程序订阅消息失败", e);
        }
    }

    /**
     * 保存记录订单操作日志
     *
     * @param orderId 订单ID
     * @param data    其他数据
     * @param remark  描述
     */
    private void saveChargeData(String comId, String orderId, Object data, String remark) {
        DataLog dataLog = new DataLog();
        dataLog.setComId(comId);
        dataLog.setChargeOrderId(orderId);
        dataLog.setAction(OrderAction.Common.PushForChargeStop.name());
        dataLog.setActionZh(OrderAction.Common.PushForChargeStop.getValue());
        dataLog.setCreateTime(new Date());
        dataLog.setJsonData(cn.hutool.json.JSONUtil.toJsonStr(data));
        dataLog.setRemark(remark);
        dataLogService.saveRow(dataLog);
    }

    private void pushMpTemplateMsg(String comId, WxMpTemplateMessage wxMpTemplateMessage){
        try {
            String msgId = wxManager.getMpService(comId).getTemplateMsgService().sendTemplateMsg(wxMpTemplateMessage);
            log.info("推送微信公众号模版消息：{}", JSONUtil.toJsonStr(wxMpTemplateMessage));
        } catch (Exception e){
            log.error("推送微信公众号模版消息失败", e);
        }
    }

    @Override
    public void pushChargeEnd(Order order) {
        try {
            Notification notification = notificationService.getRow("com_id", order.getComId());
            if (null == notification || !YesOrNo.Yes.name().equals(notification.getIsOrderEnable())) {
                return;
            }

            MemberUser user = memberUserService.getRow(order.getMemberUserId());
            if (null == user && StrUtil.isBlank(user.getMiniOpenId())) {
                return;
            }

            String page = StrUtil.EMPTY;
            String stopReason = StrUtil.EMPTY;
            String amount = String.valueOf(order.getOrderAmount() / 100D);
            switch (DeviceEnum.Type.valueOf(order.getDeviceType())) {
                case PB:
                    stopReason = OrderStopReason.PB.valueOf(order.getEndType()).getValue();
                    break;
                case EB:
                    stopReason = OrderStopReason.EB.valueOf(order.getEndType()).getValue();
                    page = "/pages/charge/charging/eb_device?id=" + order.getChargeOrderId();
                    break;
                case EV:
                    OrderStopReason.EV evStopReason = EnumUtil.fromStringQuietly(OrderStopReason.EV.class, order.getEndType());
                    stopReason = evStopReason != null ? evStopReason.getValue() : getEVStopReason(order.getEndType());
                    page = "/pages/charge/charging/ev_device?id=" + order.getOrderNo();

                    EvOrder evOrder = evOrderService.getRow("charge_order_id", order.getChargeOrderId());
                    if (null != evOrder && OrderEnum.PlaceStatus.Place.name().equals(evOrder.getPlaceStatus())) {
                        stopReason += "，进入占位中";
                    }
                    break;
                case EBox:
                    stopReason = OrderStopReason.EBox.valueOf(order.getEndType()).getValue();
                    page = "/pages/charge/charging/box_device?id=" + order.getChargeOrderId();
                    amount = "--";
                    break;
            }

            WxMaSubscribeMessage message = new WxMaSubscribeMessage();
            message.setTemplateId(notification.getStopTplId());
            message.setToUser(user.getMiniOpenId());
            message.setMiniprogramState(WxMaConstants.MiniProgramState.FORMAL);
            message.setPage(page);
            message.addData(new WxMaSubscribeMessage.MsgData("character_string1", order.getOrderNo()));
            message.addData(new WxMaSubscribeMessage.MsgData("character_string14", order.getDeviceCode()));
            message.addData(new WxMaSubscribeMessage.MsgData("amount6", amount));
            message.addData(new WxMaSubscribeMessage.MsgData("time7", DateUtil.format(order.getEndTime(),
                    DatePattern.NORM_DATETIME_PATTERN)));
            message.addData(new WxMaSubscribeMessage.MsgData("thing9", StrUtil.subPre(stopReason, 20)));
            pushMiniTemplateMsg(order, message);
        }catch (Exception ex){
            log.error("结束充电推送失败：{}",ex.getMessage());
        }
    }

    @Override
    public void pushDeviceOffline(Pile device) {
        Notification notification = notificationService.getRow("com_id", device.getComId());
        if(null == notification || !YesOrNo.Yes.name().equals(notification.getIsMpEnable())){
            return;
        }

        Station station = stationService.getRow("device_station_id", device.getDeviceStationId());
        if(null == station){
            return;
        }
        String address = StrUtil.builder(station.getProvince(), station.getCity(), station.getArea(), station.getAddress()).toString();

        List<Map> adminList = JSONUtil.toList(notification.getAdminIds(), Map.class);
        if(null == adminList){
            return;
        }

        WxMpTemplateMessage message = new WxMpTemplateMessage();
        message.setTemplateId(notification.getOfflineTplId()); // 模板编号：43716
        message.addData(new WxMpTemplateData("character_string1", device.getCode()));
        message.addData(new WxMpTemplateData("thing2", StrUtil.subPre(device.getName(), 20)));
        message.addData(new WxMpTemplateData("thing3", StrUtil.subPre(address, 20)));
        message.addData(new WxMpTemplateData("time4", DateUtil.format(device.getLastOfflineTime(),
                DatePattern.NORM_DATETIME_PATTERN)));

        // 5分钟后设备仍离线就推送
        taskScheduler.schedule(() -> pushDeviceOffline(device.getDevicePileId(), adminList, message),
                DateUtil.date().offset(DateField.MINUTE, 5));
    }

    @Override
    public void pushDeviceFault(Notification notification,List<String> openIds,String stationName, String deviceCode, Integer port, String faultType, Date faultTime) {
       WxMpTemplateMessage message = new WxMpTemplateMessage();
       message.setTemplateId(notification.getAlarmTplId()); // 模板编号：47959
       message.addData(new WxMpTemplateData("thing2", StrUtil.subPre(stationName, 20)));
       message.addData(new WxMpTemplateData("character_string4", StrUtil.subPre(deviceCode, 20)));
       message.addData(new WxMpTemplateData("character_string8", String.valueOf(port)));
       message.addData(new WxMpTemplateData("thing5", StrUtil.subPre(faultType, 20)));
       message.addData(new WxMpTemplateData("time6", DateUtil.format(faultTime, DatePattern.NORM_DATETIME_PATTERN)));

    }

    // @Async
    protected void pushDeviceOffline(String devicePileId, List<Map> adminList, WxMpTemplateMessage message){
        Pile pile = pileService.getRow(devicePileId);
        if(null == pile || !StrUtil.equals(pile.getDeviceStatus(), DeviceEnum.DeviceStatus.Offline.name())){
            return;
        }
        Station station = stationService.getRow("device_station_id", pile.getDeviceStationId());
        if(null == station){
            return;
        }
        Merchant merchant = merchantService.getRow("platform_merchant_id", station.getPlatformMerchantId());
        if(null == merchant){
            return;
        }
        adminList.stream().forEach(admin -> {
            String openid = (String) admin.get("openid");
            if(StrUtil.equals(openid, merchant.getMpOpenId())){
                message.setToUser(openid);
                pushMpTemplateMsg(pile.getComId(), message);
            }
        });
    }

    /**
     * 推送订单投诉：管理员
     *
     * @param order
     */
    @Override
    public void pushComplaintOrder(Order order) {
        Notification notification = notificationService.getRow("com_id", order.getComId());
        if(null == notification || !YesOrNo.Yes.name().equals(notification.getIsMpEnable())){
            return;
        }

        MemberUser user = memberUserService.getRow(order.getMemberUserId());
        if (null == user) {
            return;
        }
        Station station = stationService.getRow("device_station_id", order.getDeviceStationId());
        if(null == station){
            return;
        }
        Merchant merchant = merchantService.getRow("platform_merchant_id", station.getPlatformMerchantId());
        if(null == merchant){
            return;
        }
        List<Map> adminList = JSONUtil.toList(notification.getAdminIds(), Map.class);
        if(null == adminList){
            return;
        }

        adminList.stream().forEach(admin -> {
            String openid = (String) admin.get("openid");
            if(StrUtil.equals(openid, merchant.getMpOpenId())){
                WxMpTemplateMessage message = new WxMpTemplateMessage();
                message.setTemplateId(notification.getComplaintTplId()); // 模板编号：49703
                message.setToUser(openid);
                message.addData(new WxMpTemplateData("thing1", StrUtil.subPre(user.getNickname(), 20)));
                message.addData(new WxMpTemplateData("character_string2", String.valueOf(order.getOrderNo())));
                message.addData(new WxMpTemplateData("phone_number4", user.getMobile()));
                pushMpTemplateMsg(order.getComId(), message);
            }
        });


    }


    private String getEVStopReason(String endType){
        StopType stopType = EnumUtil.fromStringQuietly(StopType.class,endType);
        if(stopType != null){
            return stopType.getKey();
        }else{
            return "未知原因";
        }
    }
}
